#ifndef SSD1306_OLED_H
#define SSD1306_OLED_H

#include "headfile.h"
#include "I2C.h"
#include "SPI.h"
//#include "General_GUI.h"
#include "Adafruit_GFX.h"
#include "FONT.h"

typedef enum
{
    SSD1306_SPI,
    SSD1306_I2C
} SSD1306_I2C_SPI_mode;

class SSD1306_Base
{
protected:
    I2C *i2c;
    uint8_t i2c_addr;

    SPI *spi;
    Pin_enum dc;
    Pin_enum cs;
    Pin_enum rst;

    SSD1306_I2C_SPI_mode mode;

    uint8_t send_cmd(uint8_t);
    uint8_t send_data(uint8_t);
    uint8_t send_data(uint8_t, int);
    uint8_t send_data(const uint8_t *, int);
    void init();

public:
    SSD1306_Base(I2C *i2c_class, uint8_t addr = 0x78, Pin_enum rst_pin = Pin_null)
    {
        mode = SSD1306_I2C;
        i2c = i2c_class;
        i2c_addr = addr;
        rst = rst_pin;
        // init();
    }

    SSD1306_Base(SPI *spi_class, Pin_enum CS, Pin_enum DC, Pin_enum rst_pin = Pin_null)
    {
        mode = SSD1306_SPI;
        spi = spi_class;
        dc = DC;
        cs = CS;
        rst = rst_pin;
    }

    ~SSD1306_Base(){};

    int begin();
    int stop();

    int chack();
    void setLight(uint8_t);
    void setShowMode(uint8_t);

    virtual void clear() = 0;
    // virtual void show() = 0;
};

#define SSD1306_WHITE GFXcanvas1_SET
#define SSD1306_BLACK GFXcanvas1_RESET
#define SSD1306_INVERSE GFXcanvas1_INVERSE

class SSD1306_GUI : public SSD1306_Base, public Adafruit_GFX
{
    uint8_t buffer[1024];

public:
    SSD1306_GUI(I2C *i2c_class, uint8_t addr = 0x78, Pin_enum rst_pin = Pin_null) : SSD1306_Base(i2c_class, addr, rst_pin), Adafruit_GFX(128, 64)
    {
        setCursor(0, 0);
        setTextColor(SSD1306_WHITE);
        setTextSize(1);
    };
    SSD1306_GUI(SPI *spi_class, Pin_enum CS, Pin_enum DC, Pin_enum rst_pin = Pin_null) : SSD1306_Base(spi_class, CS, DC, rst_pin), Adafruit_GFX(128, 64)
    {
        setCursor(0, 0);
        setTextColor(SSD1306_WHITE);
        setTextSize(1);
    }

    virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
    virtual void clear();
    virtual void show();
};

/***************************************************************************/

class SSD1306_Console : public SSD1306_Base, public outputStream
{
    font *text_font;
    int write_line, write_x;

public:
    SSD1306_Console(I2C *i2c_class, uint8_t addr = 0x78, Pin_enum rst_pin = Pin_null) : SSD1306_Base(i2c_class, addr, rst_pin)
    {
        setFont(&ASCII_5x8);
        setPoint(0, 0);
    };
    SSD1306_Console(SPI *spi_class, Pin_enum CS, Pin_enum DC, Pin_enum rst_pin = Pin_null) : SSD1306_Base(spi_class, CS, DC, rst_pin)
    {
        setFont(&ASCII_5x8);
        setPoint(0, 0);
    };

    void setFont(font *new_font) { text_font = new_font; };
    void setLine(int line) { write_line = line; };
    void setPoint(int line, int x) { write_line = line, write_x = x; };

    virtual size_t write(uint8_t);
    virtual size_t write(const uint8_t *, size_t);

    virtual void clear();
};

#endif
